-
Notifications
You must be signed in to change notification settings - Fork 59
feat: implement HTTP allowed hosts/origins checking #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
87cefa1
to
85834d5
Compare
85834d5
to
e2c72e6
Compare
e2c72e6
to
f1b18a2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, --allowed-hosts
currently performs strict matching of both the host and port. This is unintuitive and as far as I can tell other frameworks match just on the hostname and not the port. For example, Rails' ActionDispatch::HostAuthorization middleware appears to strip the port before matching the host header.
8f2d898
to
d2400b9
Compare
cmd/server/server_test.go
Outdated
@@ -141,17 +155,17 @@ func TestServerCmd_AllArgs_Defaults(t *testing.T) { | |||
{"chat-base-path default", FlagChatBasePath, "/chat", func() any { return viper.GetString(FlagChatBasePath) }}, | |||
{"term-width default", FlagTermWidth, uint16(80), func() any { return viper.GetUint16(FlagTermWidth) }}, | |||
{"term-height default", FlagTermHeight, uint16(1000), func() any { return viper.GetUint16(FlagTermHeight) }}, | |||
{"allowed-hosts default", FlagAllowedHosts, []string{"localhost"}, func() any { return viper.GetStringSlice(FlagAllowedHosts) }}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also allow 127.0.0.1
and [::1]
by default?
cmd/server/server.go
Outdated
if len(input) == 0 { | ||
return fmt.Errorf("the list must not be empty") | ||
} | ||
for _, item := range input { | ||
for _, r := range item { | ||
if unicode.IsSpace(r) { | ||
return fmt.Errorf("'%s' contains whitespace characters, which are not allowed", item) | ||
} | ||
} | ||
if strings.Contains(item, ",") { | ||
return fmt.Errorf("'%s' contains comma characters, which are not allowed", item) | ||
} | ||
} | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we validate AllowedOrigins in the HTTP layer but AllowedHosts here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We validate both in both the HTTP layer and the cmd layer. Originally because I wanted to keep cmd-specific validation, like whitespace and comma detection, to the cmd layer. But it did lead to a bunch of duplication, which I'm not happy about. I'll refactor to keep validation in a single place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have any further blocking comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Since coder/agentapi#49 was merged, agentapi by default only accepts requests with the `Host` header set to localhost, 127.0.0.1, or [::1]. In Coder, agentapi is served behind a reverse proxy as a workspace app, so we need to use a wildcard `AGENTAPI_ALLOWED_HOSTS` for agentapi-based modules to continue working. This PR updates the claude code and agentapi modules, and a subsequent PR will update modules that are based on the agentapi module.
This PR adds 2 new CLI flags:
--allowed-hosts
and--allowed-origins
. They control what kinds ofHost
andOrigin
headers the server accepts.